#pragma once
#include <map>
#include <vector>
#include <IceUtil\Shared.h>
#include <IceUtil\Mutex.h>
#include <IceUtil\Monitor.h>

namespace Xts
{
	namespace Util
	{
		template<typename KeyType, typename ValueType>
		class XThreadSafeDictionary : public ::IceUtil::Monitor<::IceUtil::Mutex>, public ::IceUtil::Shared
		{
		public:
			XThreadSafeDictionary(void);
			~XThreadSafeDictionary(void);

			bool Insert(const KeyType& key, const ValueType& value);
			bool Delete(const KeyType& key);
			bool ContainsKey(const KeyType& key)const;
			bool GetItem(const KeyType& key, ValueType& value);
			void SetItem(const KeyType& key, const ValueType& value);
			//Any item in outmap would not be deleted. If there is already the same key in outmap, 
			//its value would be changed; otherwise, a new item would be inserted in outmap.
			void CopyToMap(::std::map<KeyType, ValueType>& outmap)const;

			::std::vector<KeyType> Keys()const;
			::std::vector<ValueType> Values()const;

			size_t Size()const;

			/*const ValueType& operator[](const KeyType& key)const;
			ValueType& operator[](const KeyType& key);*/

		protected:
			::std::map<KeyType, ValueType> x_dictionary;
		};

		template<typename KeyType, typename ValueType>
		XThreadSafeDictionary<KeyType, ValueType>::XThreadSafeDictionary(void)
		{
		}

		template<typename KeyType, typename ValueType>
		XThreadSafeDictionary<KeyType, ValueType>::~XThreadSafeDictionary(void)
		{
			x_dictionary.clear();
		}

		template<typename KeyType, typename ValueType>
		bool XThreadSafeDictionary<KeyType, ValueType>::Insert(const KeyType& key, const ValueType& value)
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);

			typedef std::pair <KeyType, ValueType> Insert_Pair;
			return x_dictionary.insert(Insert_Pair(key, value)).second;
		}

		template<typename KeyType, typename ValueType>
		bool XThreadSafeDictionary<KeyType, ValueType>::Delete(const KeyType& key)
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			::std::map<KeyType, ValueType>::iterator Iter = x_dictionary.find(key);
			if (Iter != x_dictionary.end())
			{
				x_dictionary.erase(Iter);
				return true;
			}

			return false;
		}

		template<typename KeyType, typename ValueType>
		bool XThreadSafeDictionary<KeyType, ValueType>::ContainsKey(const KeyType& key)const
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			if (x_dictionary.find(key) != x_dictionary.end())
				return true;

			return false;
		}

		template<typename KeyType, typename ValueType>
		bool XThreadSafeDictionary<KeyType, ValueType>::GetItem(const KeyType &key, ValueType &value)
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			::std::map<KeyType, ValueType>::iterator Iter = x_dictionary.find(key);
			if (Iter != x_dictionary.end())
			{
				value = Iter->second;
				return true;
			}

			return false;

		}

		template<typename KeyType, typename ValueType>
		void XThreadSafeDictionary<KeyType, ValueType>::SetItem(const KeyType &key, const ValueType &value)
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			::std::map<KeyType, ValueType>::iterator Iter = x_dictionary.find(key);
			if (Iter != x_dictionary.end())
			{
				Iter->second = value;
			}
			else
			{
				typedef std::pair <KeyType, ValueType> Insert_Pair;
				x_dictionary.insert(Insert_Pair(key, value));
			}
		}

		template<typename KeyType, typename ValueType>
		void XThreadSafeDictionary<KeyType, ValueType>::CopyToMap(std::map<KeyType, ValueType>& outmap)const
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);

			::std::map<KeyType, ValueType>::const_iterator Iter;
			for (Iter = x_dictionary.cbegin(); Iter != x_dictionary.cend(); Iter++)
			{
				outmap[Iter->first] = Iter->second;
			}
		}

		template<typename KeyType, typename ValueType>
		::std::vector<KeyType> XThreadSafeDictionary<KeyType, ValueType>::Keys()const
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			::std::vector<KeyType> itKeys;
			::std::map<KeyType, ValueType>::const_iterator cIter;
			for (cIter = x_dictionary.begin(); cIter != x_dictionary.end(); cIter++)
			{
				itKeys.push_back(cIter->first);
			}
			return itKeys;
		}

		template<typename KeyType, typename ValueType>
		::std::vector<ValueType> XThreadSafeDictionary<KeyType, ValueType>::Values()const
		{
			::IceUtil::Monitor<::IceUtil::Mutex>::Lock lock(*this);
			::std::vector<ValueType> itValues;
			::std::map<KeyType, ValueType>::const_iterator cIter;
			for (cIter = x_dictionary.begin(); cIter != x_dictionary.end(); cIter++)
			{
				itValues.push_back(cIter->second);
			}
			return itValues;
		}

		template<typename KeyType, typename ValueType>
		size_t XThreadSafeDictionary<KeyType, ValueType>::Size()const
		{
			return x_dictionary.size();
		}

	}
}


